home *** CD-ROM | disk | FTP | other *** search
/ GRAVIS Top 100 #3 / GRAVIS CD No3_Fruhjahr_95.cdr / GRAVIS / PD u. Shareware / Bildschirmschoner / Basic Black 1.4.1 / Source / BBinit.c < prev    next >
C/C++ Source or Header  |  1994-08-09  |  23KB  |  790 lines

  1. /*********************************************************************
  2.  * Basic Black ©1993,1994 by Mason L. Bliss
  3.  * All Rights Reserved
  4.  * - version 1.4.1 -
  5.  *
  6.  * The trap patching shell is taken from a neat little program
  7.  * Mike Scanlin wrote for the August '92 MacTutor.
  8.  *
  9.  * Basic Black's screen-blanking routine was inspired by code written
  10.  * by Christopher Tate. (Public Blanket)
  11.  *
  12.  * Basic Black makes use of CShowProc, by Ken McLeod, to show its
  13.  * icon animation at startup time.
  14.  *
  15.  * Basic Black would be nowhere near as nice as it is without the
  16.  * consistent help of my beta testers, who are listed in the Basic Black
  17.  * read-me file. Thank you! ;-)
  18.  *
  19.  *********************************************************************/
  20.  
  21. #include <GestaltEqu.h>
  22. #include <ShutDown.h>
  23. #include <Traps.h>
  24. #include "BB.h"
  25. #include "BBinit.h"
  26.  
  27.  
  28.  
  29. /*********************************************************************
  30.  * main:
  31.  *
  32.  * Gets memory in the system heap, installs our patches, and initializes
  33.  * our patch globals. This is the only routine that gets executed at
  34.  * startup time (by the INIT mechanism).
  35.  *
  36.  * Note that the code resource should be purgeable. The routines listed
  37.  * below aren't used - the code, after it's loaded, is COPIED into the
  38.  * area we set up in the system heap, after which the originals are
  39.  * discarded, as it's the COPIES that are used. If the code resource is
  40.  * set to "Not Purgeable" then the originals - which are never again
  41.  * referenced - stick around until shutdown time, wasting memory.
  42.  *
  43.  * Also, with Think C, make sure that "Custom Headers" is turned on.
  44.  *
  45.  * The block of memory that we allocate will look like this when main()
  46.  * has finished:
  47.  *
  48.  *                     +--------------------+
  49.  *                     |      PatchGlobals      |
  50.  *                     +--------------------+
  51.  *                     |  StartPatchCode()  |
  52.  *     SE trap addr -> +--------------------+
  53.  *                     |  MySystemEvent()   |
  54.  *     IC trap addr -> +--------------------+
  55.  *                     |  MyInitCursor()    |
  56.  *    DMB trap addr -> +--------------------+
  57.  *                     |  MyDrawMenuBar()   |
  58.  *     ER trap addr -> +--------------------+
  59.  *                     |  MyEraseRect()     |
  60.  *     EO trap addr -> +--------------------+
  61.  *                     |  MyEraseOval()     |
  62.  *     EG trap addr -> +--------------------+
  63.  *                     |  MyEraseRgn()      |
  64.  *     ST trap addr -> +--------------------+
  65.  *                     |  MySystemTask()    |
  66.  *                     +--------------------+
  67.  *                     |  FallAsleep()      |
  68.  *                     +--------------------+
  69.  *                     |  WakeUp()          |
  70.  *                     +--------------------+
  71.  *                     |  abs()             |
  72.  *                     +--------------------+
  73.  *                     |  DrawClock()       |
  74.  *                     +--------------------+
  75.  *                     |  RemoveICPatch()   |
  76.  *                     +--------------------+
  77.  *                     |  BBlkSelector()    |
  78.  *                     +--------------------+
  79.  *                     |  SAVRSelector()    |
  80.  *                     +--------------------+
  81.  *                     |  SAVCSelector()    |
  82.  *                     +--------------------+
  83.  *                     |  SaverControl()    |
  84.  *                     +--------------------+
  85.  *                     |  EndPatchCode()    |
  86.  *                     +--------------------+
  87.  *
  88.  *********************************************************************/
  89. void main()
  90. {
  91.     Ptr                    patchPtr;
  92.     PatchGlobalsPtr        pgPtr;
  93.     long                codeSize, offset, oldA5;
  94.     QDGlobals            qd;
  95.     GrafPort            gp;
  96.     Handle                procH;
  97.     PrefStructureHandle    prefHandle;
  98.     Boolean                drawStartupIcon = false;
  99.     
  100.     /* try and get some memory in the system heap for code and globals */
  101.     codeSize = (long) EndPatchCode - (long) StartPatchCode;
  102.     patchPtr = NewPtrSys(codeSize + sizeof(PatchGlobals));
  103.     if (!patchPtr) {
  104.         /* put up the error icon */
  105.         if ((procH = GetIndResource('PROC', 1)) != 0L) {
  106.             HLock(procH);
  107.             CallPascal(128, -1, *procH);
  108.             HUnlock(procH);
  109.             ReleaseResource(procH);
  110.         }
  111.         return;    /* out of memory -- abort patching */
  112.     }
  113.  
  114.     /* Set up pgPtr */
  115.     pgPtr = (PatchGlobalsPtr) patchPtr;
  116.     
  117.     /* Read the configuration information from our 'PREF' resource. */
  118.     prefHandle = (PrefStructureHandle) GetIndResource('PREF', 1);
  119.  
  120.     pgPtr->pgVersion = (**prefHandle).version;
  121.  
  122.     pgPtr->pgMustSleep = false;
  123.     pgPtr->pgIntervalTime = 20;                /* Three times per second */
  124.     
  125.     pgPtr->pgSleepRect = (**prefHandle).sleepNowCorner;
  126.     pgPtr->pgWakeRect = (**prefHandle).sleepNeverCorner;
  127.     pgPtr->pgIdleTicks = ((long) (**prefHandle).idleTime) * 3600;
  128.     pgPtr->pgBouncingClock = (**prefHandle).bounceClock;
  129.     pgPtr->pgMustSave = (**prefHandle).saverOn;
  130.     pgPtr->pgRefreshTime = (**prefHandle).refreshSeconds * 60;
  131.     pgPtr->pgMenubarKluge = (**prefHandle).zeroBar;
  132.  
  133.  
  134.     drawStartupIcon = (**prefHandle).showIcon;
  135.  
  136.     if ((**prefHandle).fadeToWhite) {                // Fade to white
  137.         StuffHex(&(pgPtr->pgForePat), "\pFFFFFFFFFFFFFFFF");
  138.         StuffHex(&(pgPtr->pgBackPat), "\p0000000000000000");
  139.     } else {                                        // Fade to black
  140.         StuffHex(&(pgPtr->pgForePat), "\p0000000000000000");
  141.         StuffHex(&(pgPtr->pgBackPat), "\pFFFFFFFFFFFFFFFF");
  142.     }
  143.  
  144.     /* initialize the patch globals at the beginning of the block */
  145.     pgPtr->pgOldSE = (SEProcPtr) GetTrapAddress(_SystemEvent);
  146.     pgPtr->pgOldIC = (ICProcPtr) GetTrapAddress(_InitCursor);
  147.     pgPtr->pgOldDMB = (DMBProcPtr) GetTrapAddress(_DrawMenuBar);
  148.     pgPtr->pgOldER = (ERProcPtr) GetTrapAddress(_EraseRect);
  149.     pgPtr->pgOldEO = (EOProcPtr) GetTrapAddress(_EraseOval);
  150.     pgPtr->pgOldEG = (EGProcPtr) GetTrapAddress(_EraseRgn);
  151.     pgPtr->pgOldST = (STProcPtr) GetTrapAddress(_SystemTask);
  152.  
  153.     /* move the code into place after the globals */
  154.     BlockMove(StartPatchCode, patchPtr + sizeof(PatchGlobals), codeSize);
  155.     
  156.     /* set whatever patches seem appropriate at the time */
  157.     patchPtr += sizeof(PatchGlobals);
  158.  
  159.     offset = (long) MySystemEvent - (long) StartPatchCode;
  160.     SetTrapAddress((long) patchPtr + offset, _SystemEvent);
  161.  
  162.     offset = (long) MySystemTask - (long) StartPatchCode;
  163.     SetTrapAddress((long) patchPtr + offset, _SystemTask);
  164.  
  165.     if ((**prefHandle).initCursorPatch) {
  166.         offset = (long) MyInitCursor - (long) StartPatchCode;
  167.         SetTrapAddress((long) patchPtr + offset, _InitCursor);
  168.  
  169.         /* install shutdown procedure only if InitCursor patch is installed */
  170.         offset = (long) RemoveICPatch - (long) StartPatchCode;
  171.         ShutDwnInstall( (ShutDwnProcPtr) ((long) patchPtr + offset),
  172.                                                     sdRestartOrPower + sdOnDrivers);
  173.     }
  174.  
  175.     if ((**prefHandle).drawMenuBarPatch) {
  176.         offset = (long) MyDrawMenuBar - (long) StartPatchCode;
  177.         SetTrapAddress((long) patchPtr + offset, _DrawMenuBar);
  178.     }
  179.  
  180.     if ((**prefHandle).eraseRectPatch) {
  181.         offset = (long) MyEraseRect - (long) StartPatchCode;
  182.         SetTrapAddress((long) patchPtr + offset, _EraseRect);
  183.     }
  184.  
  185.     if ((**prefHandle).eraseOvalPatch) {
  186.         offset = (long) MyEraseOval - (long) StartPatchCode;
  187.         SetTrapAddress((long) patchPtr + offset, _EraseOval);
  188.     }
  189.  
  190.     if ((**prefHandle).eraseRgnPatch) {
  191.         offset = (long) MyEraseRgn - (long) StartPatchCode;
  192.         SetTrapAddress((long) patchPtr + offset, _EraseRgn);
  193.     }
  194.     
  195.     /* We're done with our prefs, so we might as well get rid of it now. */
  196.     ReleaseResource(prefHandle);
  197.  
  198.  
  199.     /* install a new 'BBlk' gestalt selector */
  200.     offset = (long) BBlkSelector - (long) StartPatchCode;
  201.     NewGestalt('BBlk', (ProcPtr) ((long) patchPtr + offset));
  202.  
  203.     /* install a new 'SAVR' gestalt selector */
  204.     offset = (long) SAVRSelector - (long) StartPatchCode;
  205.     NewGestalt('SAVR', (ProcPtr) ((long) patchPtr + offset));
  206.  
  207.     /* install a new 'SAVC' gestalt selector */
  208.     offset = (long) SAVCSelector - (long) StartPatchCode;
  209.     NewGestalt('SAVC', (ProcPtr) ((long) patchPtr + offset));
  210.     
  211.     pgPtr->pgSaverOn = false;
  212.     pgPtr->pgMustSleep = false;
  213.     pgPtr->pgMustWake = false;
  214.     pgPtr->pgInSleepRect = false;
  215.     pgPtr->pgLastAction = Ticks;
  216.     pgPtr->pgLastCheck = Ticks;
  217.     pgPtr->pgLastRefresh = Ticks;
  218.         
  219.     
  220.     /* Read in the clock background picture. */
  221.     /* This assumes no errors - we'll correct the assumption in the next released. */
  222.     pgPtr->pgClockBg = (PicHandle) GetResource('PICT', 255);
  223.     DetachResource(pgPtr->pgClockBg);
  224.  
  225.     
  226.     /* The next three lines fake out some QuickDraw globals so we can
  227.         figure out the correct sleep and wake rectangles, as we don't
  228.         have access to the 'proper' QuickDraw globals. */
  229.     oldA5 = SetA5((long) &qd.qdend);    // Point A5 at our fake globals
  230.     InitGraf(&qd.thePort);                // ...and initialize 'em
  231.     OpenPort((GrafPtr) &gp);
  232.         
  233.     pgPtr->pgCorners[0].left = (gp.portRect).left - 1;        // top left
  234.     pgPtr->pgCorners[0].right = (gp.portRect).left + 8;
  235.     pgPtr->pgCorners[0].top = (gp.portRect).top - 1;
  236.     pgPtr->pgCorners[0].bottom = (gp.portRect).top + 8;
  237.  
  238.     pgPtr->pgCorners[1].left = (gp.portRect).right - 8;        // top right
  239.     pgPtr->pgCorners[1].right = (gp.portRect).right + 1;
  240.     pgPtr->pgCorners[1].top = (gp.portRect).top - 1;
  241.     pgPtr->pgCorners[1].bottom = (gp.portRect).top + 8;
  242.  
  243.     pgPtr->pgCorners[2].left = (gp.portRect).right - 8;        // bottom right
  244.     pgPtr->pgCorners[2].right = (gp.portRect).right + 1;
  245.     pgPtr->pgCorners[2].top = (gp.portRect).bottom - 8;
  246.     pgPtr->pgCorners[2].bottom = (gp.portRect).bottom + 1;
  247.  
  248.     pgPtr->pgCorners[3].left = (gp.portRect).left - 1;        // bottom left
  249.     pgPtr->pgCorners[3].right = (gp.portRect).left + 8;
  250.     pgPtr->pgCorners[3].top = (gp.portRect).bottom - 8;
  251.     pgPtr->pgCorners[3].bottom = (gp.portRect).bottom + 1;
  252.     
  253.     ClosePort((GrafPtr) &gp);
  254.     oldA5 = SetA5(oldA5);                // Restore A5 to its previous value
  255.  
  256.  
  257.     /* put up our icon animation because the nice user wants us to */
  258.     if (drawStartupIcon && (procH = GetIndResource('PROC', 1)) != 0L)    {
  259.         HLock(procH);
  260.         /* put up either the normal icon, or the 'off' icon, as appropriate */
  261.         if (pgPtr->pgMustSave)
  262.             CallPascal(-4064, -1, *procH);
  263.         else
  264.             CallPascal(257, -1, *procH);
  265.         HUnlock(procH);
  266.     }
  267.     ReleaseResource(procH);
  268. }
  269.  
  270.  
  271.  
  272. /*********************************************************************
  273.  * StartPatchCode:
  274.  *
  275.  * Dummy proc to mark the beginning of the code for the
  276.  * patches. Make sure all of your patch code is between
  277.  * here and EndPatchCode.
  278.  *
  279.  *********************************************************************/
  280. void StartPatchCode()
  281. {
  282. }
  283.  
  284.  
  285.  
  286. /*********************************************************************
  287.  * MySystemEvent:
  288.  *
  289.  * Tail patch on SystemEvent.
  290.  *
  291.  * The reason this returns a short instead of a Boolean is because we
  292.  * need to make sure the low byte of the top word on the stack is zero
  293.  * because some programs do a Tst.W (SP)+ when this returns instead of
  294.  * Tst.B (SP)+ like they should (which is technically their bug but, we
  295.  * might as well work around it since it's not hard).
  296.  *
  297.  * If you want to eat the event (not pass it on to the caller) then set
  298.  * returnValue to true.
  299.  *
  300.  *********************************************************************/
  301. pascal short MySystemEvent(EventRecord *theEvent)
  302. {
  303.     PatchGlobalsPtr    pgPtr;
  304.     short            returnValue;
  305.     register short    foo;
  306.     
  307.     /* find our globals */
  308.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  309.     
  310.     /* call original SE first */
  311.     returnValue = (*pgPtr->pgOldSE) (theEvent);
  312.     
  313.     if ((foo = theEvent->what) >= 1 && foo <= 5 || foo == 7) {
  314.         pgPtr->pgLastAction = Ticks;        /* Update last time counter */
  315.         pgPtr->pgInSleepRect = false;
  316.         if (pgPtr->pgSaverOn) {
  317.             if (foo != 7) {                    /* mask keypresses and clicks */
  318.                 returnValue = true;            /* we've "handled" the event */
  319.                 theEvent->what = 0;
  320.             }
  321.             pgPtr->pgMustWake = true;
  322.         }
  323.     }
  324.     
  325.     /* return to original caller */
  326.     return returnValue;
  327. }
  328.  
  329.  
  330.  
  331. /*********************************************************************
  332.  * MyInitCursor:
  333.  *
  334.  * Optional patch that disables InitCursor if we're asleep.
  335.  *
  336.  *********************************************************************/
  337. pascal void MyInitCursor()
  338. {
  339.     PatchGlobalsPtr    pgPtr;
  340.     
  341.     /* find our globals */
  342.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  343.     
  344.     /* call original IC first */
  345.     if (pgPtr->pgSaverOn == false)
  346.         (*pgPtr->pgOldIC) ();
  347. }
  348.  
  349.  
  350.  
  351. /*********************************************************************
  352.  * MyDrawMenuBar:
  353.  *
  354.  * Optional patch that disables DrawMenuBar if we're asleep.
  355.  *
  356.  *********************************************************************/
  357. pascal void MyDrawMenuBar()
  358. {
  359.     PatchGlobalsPtr    pgPtr;
  360.     
  361.     /* find our globals */
  362.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  363.     
  364.     /* call original DMB first */
  365.     if (pgPtr->pgSaverOn == false)
  366.         (*pgPtr->pgOldDMB) ();
  367. }
  368.  
  369.  
  370.  
  371. /*********************************************************************
  372.  * MyEraseRect:
  373.  *
  374.  * Optional patch that disables EraseRect if we're asleep.
  375.  *
  376.  *********************************************************************/
  377. pascal void MyEraseRect(Rect *rect)
  378. {
  379.     PatchGlobalsPtr    pgPtr;
  380.     
  381.     /* find our globals */
  382.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  383.     
  384.     /* call original ER first */
  385.     if (pgPtr->pgSaverOn == false)
  386.         (*pgPtr->pgOldER) (rect);
  387. }
  388.  
  389.  
  390.  
  391. /*********************************************************************
  392.  * MyEraseOval:
  393.  *
  394.  * Optional patch that disables EraseOval if we're asleep.
  395.  *
  396.  *********************************************************************/
  397. pascal void MyEraseOval(Rect *rect)
  398. {
  399.     PatchGlobalsPtr    pgPtr;
  400.     
  401.     /* find our globals */
  402.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  403.     
  404.     /* call original EO first */
  405.     if (pgPtr->pgSaverOn == false)
  406.         (*pgPtr->pgOldEO) (rect);
  407. }
  408.  
  409.  
  410.  
  411. /*********************************************************************
  412.  * MyEraseRgn:
  413.  *
  414.  * Optional patch that disables EraseRgn if we're asleep.
  415.  *
  416.  *********************************************************************/
  417. pascal void MyEraseRgn(RgnHandle rgn)
  418. {
  419.     PatchGlobalsPtr    pgPtr;
  420.     
  421.     /* find our globals */
  422.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  423.     
  424.     /* call original EG first */
  425.     if (pgPtr->pgSaverOn == false)
  426.         (*pgPtr->pgOldEG) (rgn);
  427. }
  428.  
  429.  
  430.  
  431. /*********************************************************************
  432.  * MySystemTask:
  433.  *
  434.  * Patches SystemTask. This is where most of our maintenance is done.
  435.  *
  436.  *********************************************************************/
  437. pascal void MySystemTask(void)
  438. {
  439.     PatchGlobalsPtr    pgPtr;
  440.     Point            mousePt;
  441.     
  442.     /* find our globals */
  443.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  444.     
  445.     /* Has enough time passed for us to run? */
  446.     if (Ticks - pgPtr->pgLastCheck > pgPtr->pgIntervalTime) {
  447.     
  448.         pgPtr->pgLastCheck = Ticks;
  449.     
  450.         /* Check to see if the mouse has moved */
  451.         GetMouse(&mousePt);
  452.         LocalToGlobal(&mousePt);
  453.         if (!EqualPt(mousePt, pgPtr->pgLastMouse)) {    /* id est, mouse moved */
  454.             pgPtr->pgLastMouse = mousePt;
  455.             pgPtr->pgLastAction = Ticks;
  456.             pgPtr->pgInSleepRect = false;
  457.             if (pgPtr->pgSaverOn)
  458.                 pgPtr->pgMustWake = true;
  459.         }
  460.         
  461.         if (!pgPtr->pgSaverOn) {    /* wide-awake maintenance */
  462.         
  463.             /* Does the nice user want us to fall asleep now? */
  464.             if (!pgPtr->pgInSleepRect &&
  465.                         PtInRect(mousePt, &pgPtr->pgCorners[pgPtr->pgSleepRect])) {
  466.     
  467.                 pgPtr->pgInSleepRect = true;
  468.                 /* Make it look like we haven't moved for a while. */
  469.                 pgPtr->pgLastAction -= ((pgPtr->pgIdleTicks) - DELAYTICKS);
  470.             } else {
  471.                 if (PtInRect(mousePt, &pgPtr->pgCorners[pgPtr->pgWakeRect]))
  472.                     pgPtr->pgLastAction = Ticks;
  473.             }
  474.             
  475.             /* Has enough idle time passed for us to fall asleep naturally? */
  476.             if ((Ticks - pgPtr->pgLastAction) > pgPtr->pgIdleTicks)
  477.                 pgPtr->pgMustSleep = true;
  478.     
  479.         } else {    /* Do sleepy-time maintenance. */
  480.         
  481.             if (!pgPtr->pgMustWake) {
  482.                 /* Take care of the refresh timing */
  483.                 if ((Ticks - pgPtr->pgLastRefresh) > pgPtr->pgRefreshTime) {
  484.                     pgPtr->pgLastRefresh = Ticks;
  485.                     pgPtr->pgMustSleep = true;
  486.                 }
  487.                 
  488.                 /* Has the menu bar been messed with? (Don't mess with me, man!) */
  489.                 /* Canvas users truly hate this. It's Aldus' fault - not mine. */
  490.                 if (pgPtr->pgMenubarKluge && MBarHeight != 0)
  491.                     pgPtr->pgMustSleep = true;
  492.             } else WakeUp();
  493.         }
  494.     
  495.         /* Do we need to fall asleep? */
  496.         if (pgPtr->pgMustSleep && pgPtr->pgMustSave)
  497.             FallAsleep();
  498.         
  499.     }
  500.     
  501.     /* Give everyone else some time! */
  502.     (*pgPtr->pgOldST) ();
  503. }
  504.  
  505.  
  506.  
  507. /*********************************************************************
  508.  * FallAsleep:
  509.  *
  510.  * This is where we black out the screen, and maybe draw a clock.
  511.  *
  512.  *********************************************************************/
  513. void FallAsleep(void)
  514. {
  515.     PatchGlobalsPtr    pgPtr;
  516.     GrafPort        myPort;
  517.     GrafPtr            oldPort;
  518.     
  519.     /* find our globals */
  520.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  521.     
  522.     /* hide the cursor */
  523.     ObscureCursor();
  524.     
  525.     /* Fix the menu bar if the kluge is on */
  526.     if (pgPtr->pgMenubarKluge)
  527.         if (MBarHeight != 0) {
  528.             pgPtr->pgOldHeight = MBarHeight;
  529.             MBarHeight = 0;
  530.         } else if (!pgPtr->pgSaverOn && MBarHeight == 0)
  531.             pgPtr->pgOldHeight = 0;
  532.     
  533.     /* Save the old port and set our new characteristics */
  534.     GetPort(&oldPort);
  535.     OpenPort(&myPort);
  536.     PenPat(pgPtr->pgForePat);
  537.     BackPat(pgPtr->pgBackPat);
  538.     
  539.     /* Get a region for everything, and paint it. */
  540.     UnionRgn(GrayRgn, myPort.visRgn, myPort.visRgn);
  541.     FillRgn(myPort.visRgn, pgPtr->pgBackPat);
  542.     
  543.     /* Draw our clock, if it's turned on. */
  544.     if (pgPtr->pgBouncingClock)
  545.         DrawClock(&myPort);
  546.     
  547.     /* Empty the visRgns of all windows */
  548.     CopyRgn(GrayRgn, myPort.visRgn);
  549.     SetEmptyRgn(GrayRgn);
  550.     CalcVisBehind((WindowPeek) FrontWindow(), myPort.visRgn);
  551.     CopyRgn(myPort.visRgn, GrayRgn);
  552.  
  553.     /* Restore the old port */
  554.     ClosePort(&myPort);
  555.     SetPort(oldPort);
  556.  
  557.     /* Set our flags */
  558.     pgPtr->pgSaverOn = true;
  559.     pgPtr->pgMustSleep = false;
  560.     pgPtr->pgLastRefresh = Ticks;
  561. }
  562.  
  563.  
  564.  
  565. /*********************************************************************
  566.  * WakeUp:
  567.  *
  568.  * This is where we liven up.
  569.  *
  570.  *********************************************************************/
  571. void WakeUp(void)
  572. {
  573.     PatchGlobalsPtr    pgPtr;
  574.     GrafPtr            oldPort;
  575.  
  576.     /* find our globals */
  577.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  578.     
  579.     pgPtr->pgMustWake = false;
  580.     pgPtr->pgSaverOn = false;
  581.     pgPtr->pgLastAction = Ticks + 60;        /* can't sleep until a second from now */
  582.     
  583.     /* restore the menu bar */
  584.     if (pgPtr->pgMenubarKluge)
  585.         MBarHeight = pgPtr->pgOldHeight;
  586.     DrawMenuBar();
  587.     
  588.     /* Grab the current port. */
  589.     GetPort(&oldPort);
  590.     
  591.     /* Redraw window frames and set update regions equal to visible regions */
  592.     PaintBehind((WindowPeek) FrontWindow(), GrayRgn);
  593.  
  594.     /* Calculate visRgns */
  595.     CalcVisBehind((WindowPeek) FrontWindow(), GrayRgn);
  596.     
  597.     /* Reset the port - the previous two toolbox calls disrupt it. */
  598.     SetPort(oldPort);
  599. }
  600.  
  601.  
  602.  
  603. /*********************************************************************
  604.  * abs:
  605.  *
  606.  * Return the absolute value of a short.
  607.  *
  608.  *********************************************************************/
  609. short abs(short x)
  610. {
  611.     return x < 0 ? -x : x;
  612. }
  613.  
  614.  
  615.  
  616. /*********************************************************************
  617.  * DrawClock:
  618.  *
  619.  * Draw an analog clock at a random place in the given
  620.  * GrafPort.
  621.  *
  622.  *********************************************************************/
  623. void DrawClock(GrafPtr myPort)
  624. {
  625.     PatchGlobalsPtr    pgPtr;
  626.     DateTimeRec        theTime;
  627.     Rect            theTimeRect;
  628.     short            mid;
  629.     
  630.     /* find our globals */
  631.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  632.  
  633.     GetTime(&theTime);
  634.     
  635.     /* find our clock rectangle */
  636.     theTimeRect.top = (abs(Random()) % (myPort->portRect.bottom - 110)) + 5;
  637.     theTimeRect.bottom = theTimeRect.top + 100;
  638.     theTimeRect.left = (abs(Random()) % (myPort->portRect.right - 110)) + 5;
  639.     theTimeRect.right = theTimeRect.left + 100;
  640.     
  641.     /* draw our background */
  642.     DrawPicture(pgPtr->pgClockBg, &theTimeRect);
  643.     
  644.     /* move the rect in, and draw the minute hand */
  645.     InsetRect(&theTimeRect, 5, 5);
  646.     PaintArc(&theTimeRect, (theTime.minute) * 6 - 3, 6);
  647.     
  648.     /* move the rect in more, and draw the hour hand */
  649.     InsetRect(&theTimeRect, 15, 15);
  650.     PaintArc(&theTimeRect, (theTime.hour % 12) * 30 - 5 + (theTime.minute / 2), 10);    
  651. }
  652.  
  653.  
  654.  
  655. /*********************************************************************
  656.  * RemoveICPatch:
  657.  *
  658.  * Shutdown procedure that replaces the InitCursor patch.
  659.  *
  660.  * This is an unspeakably evil way to do this, but since our patch
  661.  * globals are destroyed before shutdown, leading to our InitCursor
  662.  * routine gagging and dying horribly when called, there isn't any
  663.  * better way to do this that I know of. Blame Apple for not preserving
  664.  * memory to the end.
  665.  *
  666.  * Anyways, yes, this *is* what it looks like. For shutdown purposes,
  667.  * we're replacing InitCursor with ShowCursor... :/
  668.  *
  669.  *********************************************************************/
  670. pascal void RemoveICPatch()
  671. {
  672.     SetTrapAddress(GetTrapAddress(_ShowCursor), _InitCursor);
  673. }
  674.  
  675.  
  676.  
  677. /*********************************************************************
  678.  * BBlkSelector:
  679.  *
  680.  * 'BBlk' gestalt selector that provides the address of our patch
  681.  * globals. This is *much* cleaner than patching SizeResource().
  682.  *
  683.  *********************************************************************/
  684. pascal void BBlkSelector(OSType selector, long *result)
  685. {
  686.     /* find our globals ...and give 'em back! */
  687.     *result = (long) ((long) StartPatchCode - sizeof(PatchGlobals));
  688. }
  689.  
  690.  
  691.  
  692. /*********************************************************************
  693.  * SAVRSelector:
  694.  *
  695.  * 'SAVR' gestalt selector that tells the world when we're alive and
  696.  * also when we're sleeping.
  697.  *
  698.  *********************************************************************/
  699. pascal void SAVRSelector(OSType selector, long *result)
  700. {
  701.     PatchGlobalsPtr    pgPtr;
  702.     
  703.     /* find our globals */
  704.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  705.  
  706.     *result = 0;
  707.  
  708.     /* if we haven't been disabled, tell the world of our presence */
  709.     if (pgPtr->pgMustSave == true)
  710.         *result |= 1;                // saver enabled
  711.  
  712.     /* If screen is black, tell the world we're alive */
  713.     if (pgPtr->pgSaverOn == true) {
  714.         *result |= 2;                // saver asleep
  715.         *result |= 16;                // app drawing disabled
  716.     }
  717. }
  718.  
  719.  
  720.  
  721. /*********************************************************************
  722.  * SAVCSelector:
  723.  *
  724.  * The 'SAVC' gestalt selector passes back the address of our control
  725.  * routine so that other applications can control us.
  726.  *
  727.  * We can be turned on and off remotely, and we can be told to put
  728.  * the screen to sleep and wake the screen up. Neat, huh?
  729.  *
  730.  *********************************************************************/
  731. pascal void SAVCSelector(OSType selector, long *result)
  732. {
  733.     *result = (long) SaverControl;
  734. }
  735.  
  736.  
  737.  
  738. /*********************************************************************
  739.  * SaverControl:
  740.  *
  741.  * Executes a command from an application or whatever.
  742.  *
  743.  *********************************************************************/
  744. pascal OSErr SaverControl(short theCommand)
  745. {
  746.     PatchGlobalsPtr    pgPtr;
  747.     
  748.     /* find our globals */
  749.     pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode - sizeof(PatchGlobals));
  750.  
  751.     switch (theCommand) {
  752.         case eSaverWakeUp:                    // Make Basic Black wake up.
  753.             if (pgPtr->pgSaverOn)
  754.                 pgPtr->pgMustWake = true;
  755.             break;
  756.             
  757.         case eSaverSleep:                    // Make Basic Black go to sleep.
  758.             if (pgPtr->pgMustSave)
  759.                 pgPtr->pgMustSleep = true;
  760.             break;
  761.             
  762.         case eSaverOn:                        // Turn Basic Black on.
  763.             pgPtr->pgMustSave = true;
  764.             pgPtr->pgMustSleep = false;
  765.             break;
  766.             
  767.         case eSaverOff:                        // Turn Basic Black off.
  768.             if (pgPtr->pgSaverOn)
  769.                 pgPtr->pgMustWake = true;
  770.             pgPtr->pgMustSave = false;
  771.             break;
  772.     }
  773.     
  774.     return noErr;
  775. }
  776.  
  777.  
  778.  
  779. /*********************************************************************
  780.  * EndPatchCode:
  781.  *
  782.  * Dummy proc to mark the end of the code for the patches.
  783.  * Make sure all of your patch code is between here and
  784.  * StartPatchCode.
  785.  *
  786.  *********************************************************************/
  787. void EndPatchCode()
  788. {
  789. }
  790.